package com.lfs.market.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lfs.market.constants.RoleConstant;
import com.lfs.market.constants.UserConstant;
import com.lfs.market.exception.ServiceException;
import com.lfs.market.mapper.UserMapper;
import com.lfs.market.model.R;
import com.lfs.market.model.dto.*;
import com.lfs.market.model.entity.User;
import com.lfs.market.model.enums.ResultCode;
import com.lfs.market.service.SystemRoleService;
import com.lfs.market.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private SystemRoleService roleService;
    @Autowired
    private UserService userService;

    public SaTokenInfo login1(UserLoginDto request) {
        String userCode = request.getCode();
        String phone = request.getPhone();
        String redis_code = redisTemplate.opsForValue().get("check:code:" + phone);
        if (StrUtil.isEmpty(redis_code)) throw new ServiceException(ResultCode.Fail, "验证码错误");
        if (!redis_code.equals(userCode)) throw new ServiceException(ResultCode.Fail, "验证码错误");
        //1.查询用户是否存在
        User user = lambdaQuery().eq(User::getPhone, request.getPhone()).one();
        //2.不存在 自动创建用户
        if (null == user) {
            user = new User();
            String numbers = RandomUtil.randomNumbers(9);
            user.setNumber(numbers);
            user.setPhone(Long.valueOf(request.getPhone()));
            user.setProvince(request.getProvince());
            user.setCity(request.getCity());
            user.setAvatar(UserConstant.USER_AVATAR);
            user.setNickName("用户" + numbers);
            user.setCreateTime(new Date());
            user.setUpdateTime(new Date());
            user.setStatus(UserConstant.CHECK_COMPLETE);
            boolean save = save(user);
            if (!save) throw new ServiceException(ResultCode.Fail);
        } else {
            if (user.getStatus().equals(UserConstant.CHECK_FAIL)) {
                throw new ServiceException(ResultCode.Fail, "账户被禁用");
            }
            user.setProvince(request.getProvince());
            user.setCity(request.getCity());
            user.setUpdateTime(new Date());
            boolean update = updateById(user);
            if (!update) throw new ServiceException(ResultCode.Fail);
        }
        StpUtil.login(user.getId());
        redisTemplate.delete("check:code:" + request.getPhone());
        //返回token
        return StpUtil.getTokenInfo();
    }

    /**
     * 登录
     *
     * @param request
     * @return
     */
    @Override
    public SaTokenInfo login(UserLoginDto request) {
        if (StringUtils.isAnyBlank(request.getPhone(), request.getPassword())) {
            throw new ServiceException(ResultCode.Fail, "用户名或密码为空");
        }
        Pattern pattern = Pattern.compile(UserConstant.PHONE_NUMBER_PATTERN);
        Matcher matcher = pattern.matcher(request.getPhone());
        if (!matcher.matches()) {
            throw new ServiceException(ResultCode.Fail, "手机号不符合规范");
        }
        if (request.getPassword().length() < 6) {
            throw new ServiceException(ResultCode.Fail, "密码不能低于6位！");
        }

        String encryptPassword = SaSecureUtil.md5((UserConstant.SALT + request.getPassword()));
        if (lambdaQuery().eq(User::getPhone, request.getPhone()).one() == null) {
            throw new ServiceException(ResultCode.Fail, "用户不存在");
        }
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone, request.getPhone());
        wrapper.eq(User::getPassword, encryptPassword);
        User user = this.baseMapper.selectOne(wrapper);
        if (user == null) {
            throw new ServiceException(ResultCode.Fail, "密码错误");
        }
        if (user.getStatus().equals(UserConstant.CHECK_FAIL)) {
            throw new ServiceException(ResultCode.Fail, "账户被禁用");
        }
        StpUtil.login(user.getId());
        return StpUtil.getTokenInfo();
    }

    /**
     * 注册
     *
     * @param request
     * @return
     */
    @Override
    public SaTokenInfo register(UserLoginDto request) {
        if (StringUtils.isAnyBlank(request.getPhone(), request.getPassword(), request.getCheckPassword())) {
            throw new ServiceException(ResultCode.Fail, "用户名或密码为空");
        }
        Pattern pattern = Pattern.compile(UserConstant.PHONE_NUMBER_PATTERN);
        Matcher matcher = pattern.matcher(request.getPhone());
        if (!matcher.matches()) {
            throw new ServiceException(ResultCode.Fail, "手机号不符合规范");
        }
        if (request.getPassword().length() < 6) {
            throw new ServiceException(ResultCode.Fail, "密码不能低于6位！");
        }
        if (!request.getCheckPassword().equals(request.getPassword())) {
            throw new ServiceException(ResultCode.Fail, "两次密码不一致");
        }


        User u = lambdaQuery().eq(User::getPhone, request.getPhone()).one();
        if (u != null) throw new ServiceException(ResultCode.Fail, "用户已存在");

        User user = new User();
        String numbers = RandomUtil.randomNumbers(9);
        user.setNumber(numbers);
        user.setPhone(Long.valueOf(request.getPhone()));
        String encryptPassword = SaSecureUtil.md5((UserConstant.SALT + request.getPassword()));
        user.setPassword(encryptPassword);
        user.setProvince(request.getProvince());
        user.setCity(request.getCity());
        user.setAvatar(UserConstant.USER_AVATAR);
        user.setNickName(UserConstant.USER_PREFIX + numbers);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setStatus(UserConstant.CHECK_COMPLETE);

        //注册用户默认为普通用户
        user.setUserRole(RoleConstant.USER);
        boolean save = save(user);
        if (!save) throw new ServiceException(ResultCode.Fail);
        StpUtil.login(user.getId());
        return StpUtil.getTokenInfo();
    }

    /**
     * 根据用户ID查询用户信息
     *
     * @param userId
     * @return
     */
    @Override
    public User getByUserId(String userId) {
        User user = lambdaQuery().eq(User::getId, userId).one();
        return user;
    }

    /**
     * 后台创建用户
     *
     * @param dto
     */
    @Override
    public void create(SystemUserCreateDto dto) {
        User one = lambdaQuery().eq(User::getPhone, dto.getPhone()).one();
        if (one != null) {
            throw new ServiceException(ResultCode.Fail, "用户已存在");
        }
        User user = new User();
        user.setPhone(dto.getPhone());
        user.setAvatar(dto.getImage());
        user.setNickName(dto.getNickName());
        String numbers = RandomUtil.randomNumbers(9);
        user.setNumber(numbers);
        user.setStatus(UserConstant.CHECK_COMPLETE);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        save(user);
    }

    /**
     * 删除用户
     *
     * @param ids
     */
    @Override
    public void deleteUser(List<String> ids) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(User::getId, ids);
        remove(wrapper);
    }

    /**
     * 修改用户信息
     *
     * @param dto
     */
    @Override
    public void updateUser(SystemUserUpdateDto dto) {
        User user = new User();
        user.setId(dto.getId());
        user.setAvatar(dto.getImage());
        user.setNickName(dto.getNickName());
        user.setPhone(dto.getPhone());
        updateById(user);
    }

    /**
     * 管理员禁用用户
     *
     * @param userId
     */
    @Override
    public void disableUser(String userId) {
        User user = userService.getById(userId);
        if (BeanUtil.isEmpty(user)) throw new ServiceException(ResultCode.NotFindError);
        user.setStatus(UserConstant.CHECK_WAIT);
        user.setUpdateTime(new Date());
        boolean update = userService.updateById(user);
        if (!update) throw new ServiceException(ResultCode.UpdateError);
        StpUtil.logout(userId);
    }

    /**
     * 启用账号
     *
     * @param userId
     * @return
     */
    @Override
    public void ableUser(String userId) {
        User user = userService.getById(userId);
        if (BeanUtil.isEmpty(user)) throw new ServiceException(ResultCode.NotFindError);
        user.setStatus(UserConstant.CHECK_COMPLETE);
        user.setUpdateTime(new Date());
        boolean update = userService.updateById(user);
        if (!update) throw new ServiceException(ResultCode.UpdateError);
    }

    /**
     * 修改个人资料 审核成功
     *
     * @param userId
     * @return
     */
    @Override
    public void success(String userId) {
        User user = userService.getById(userId);
        if (BeanUtil.isEmpty(user)) throw new ServiceException(ResultCode.NotFindError);
        if (StrUtil.isNotEmpty(user.getCheckAvatar())) user.setAvatar(user.getCheckAvatar());
        if (StrUtil.isNotEmpty(user.getCheckNickName())) user.setNickName(user.getCheckNickName());
        if (StrUtil.isNotEmpty(user.getCheckIntro())) user.setIntro(user.getCheckIntro());
        user.setCheckAvatar("");
        user.setCheckNickName("");
        user.setCheckIntro("");
        user.setUpdateTime(new Date());
        user.setCheckStatus(UserConstant.CHECK_COMPLETE);
        boolean update = userService.updateById(user);
        if (!update) throw new ServiceException(ResultCode.UpdateError);
    }

    /**
     * 修改个人资料 审核失败
     *
     * @param
     * @return
     */
    @Override
    public void fail(String userId) {
        User user = userService.getById(userId);
        user.setUpdateTime(new Date());
        user.setCheckStatus(UserConstant.CHECK_FAIL);
        boolean update = userService.updateById(user);
        if (!update) throw new ServiceException(ResultCode.UpdateError);
    }

    @Override
    public List<User> selectUserInfo() {
        return baseMapper.selectUserInfo();
    }

    /**
     * 自定义批量插入数据
     *
     * @param userList
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insertBatch(List<User> userList) {
        baseMapper.insertBatch(userList);

    }

    @Override
    public SaTokenInfo loginPwd(UserLoginDto request) {
        User user = lambdaQuery().eq(User::getPhone, request.getPhone()).one();
        if (BeanUtil.isEmpty(user)) throw new ServiceException(ResultCode.NotFindError, "第一次登录，请选择手机号登录");
        String md5 = SaSecureUtil.md5(request.getPassword());
        if (!md5.equals(user.getPassword())) throw new ServiceException(ResultCode.Fail, "手机号或密码错误");
        user.setProvince(request.getProvince());
        user.setCity(request.getCity());
        user.setUpdateTime(new Date());
        boolean update = updateById(user);
        if (!update) throw new ServiceException(ResultCode.Fail);
        StpUtil.login(user.getId());
        return StpUtil.getTokenInfo();
    }

    @Override
    public void updateUserInfo(UpdateUserInfoDto dto) {
        String id = StpUtil.getLoginIdAsString();
        User user = getById(id);
        if (BeanUtil.isEmpty(user)) throw new ServiceException(ResultCode.NotFindError);
        user.setCheckNickName(dto.getNickName());
        user.setCheckIntro(dto.getIntro());
        user.setCheckAvatar(dto.getAvatar());
        user.setCheckStatus(0);
        boolean update = updateById(user);
        if (!update) throw new ServiceException(ResultCode.UpdateError);
    }

    @Override
    public Map getNum1UserStat() {
        return null;
    }

    @Override
    public List<Map> getUserStat() {
        LocalDate today = LocalDate.now();
        LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));

        List<Map> weeklyUserData = new ArrayList<>();
        String[] weekDays = {"周一", "周二", "周三", "周四", "周五", "周六", "周日"};

        for (int i = 0; i < 7; i++) {
            LocalDate currentDate = monday.plusDays(i);

            long newUsers = __getNewUsersCount(currentDate);
            long activeUsers = __getActiveUsersCount(currentDate);

            Map<String, Object> userData = new HashMap<>();
            userData.put("date", weekDays[i]);
            userData.put("new", newUsers);
            userData.put("active", activeUsers);

            weeklyUserData.add(userData);
        }

        return weeklyUserData;
    }


    private long __getActiveUsersCount(LocalDate currentDate) {
        //根据currentDate 获取当日0点到24点的时间戳
        long start = currentDate.atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000;
        long end = currentDate.atStartOfDay().plusDays(1).toEpochSecond(ZoneOffset.UTC) * 1000;
        Long count = lambdaQuery().between(User::getUpdateTime, start, end).count();
        return count;
    }

    private long __getNewUsersCount(LocalDate currentDate) {
        //根据currentDate 获取当日0点到24点的时间戳
        long start = currentDate.atStartOfDay().toEpochSecond(ZoneOffset.UTC) * 1000;
        long end = currentDate.atStartOfDay().plusDays(1).toEpochSecond(ZoneOffset.UTC) * 1000;
        Long count = lambdaQuery().between(User::getCreateTime, start, end).count();
        return count;
    }


    @Override
    public R<User> getUserInfo() {
        Object loginId = StpUtil.getLoginId();
        User user = lambdaQuery().eq(User::getId, loginId).one();
        if (user == null) {
            throw new ServiceException(ResultCode.NotFindError, "用户不存在");
        }
        return R.ok(user);
    }

    @Override
    public void getLoginCode(String phone) {
        redisTemplate.opsForValue().set("check:code:" + phone, "123456", 720, TimeUnit.MINUTES);
    }

    @Override
    public R<User> getUserInfo(String userId) {
        User user = lambdaQuery().eq(User::getId, userId).one();
        if (user == null) {
            throw new ServiceException(ResultCode.NotFindError, "用户不存在");
        }
        return R.ok(user);
    }

    @Override
    public void updateUserInfoDetail(UpdateUserInfoDto dto) {
        String id = StpUtil.getLoginIdAsString();
        User user = getById(id);
        if (BeanUtil.isEmpty(user)) throw new ServiceException(ResultCode.NotFindError);
        if (StrUtil.isNotEmpty(dto.getPassword())) {
            if (!dto.getPassword().equals(dto.getPasswordCheck()))
                throw new ServiceException(ResultCode.ValidateError, "输入密码不一致");
            String md5 = SaSecureUtil.md5(dto.getPassword());
            user.setPassword(md5);
        }
        boolean update = updateById(user);
        if (!update) throw new ServiceException(ResultCode.UpdateError);
    }

    /**
     * 查询用户列表
     *
     * @param dto
     * @return
     */
    @Override
    public Page<User> getUserList(UserAdminPageDto dto) {
        Page<User> page = lambdaQuery()
                .like(StrUtil.isNotEmpty(dto.getKey()), User::getNickName, dto.getKey()).or()
                .like(StrUtil.isNotEmpty(dto.getKey()), User::getNumber, dto.getKey())
                .eq(null != dto.getCheckStatus(), User::getCheckStatus, dto.getCheckStatus())
                .orderByDesc(User::getCreateTime)
                .page(new Page<>(dto.getPageNumber(), dto.getPageSize()));
        return page;
    }


}




